package com.zucc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.zucc.controller.req.AttachmentSearchReq;
import com.zucc.controller.resp.AttachmentResp;
import com.zucc.entity.Attachment;
import com.zucc.entity.AttachmentMapper;
import com.zucc.entity.ResourceMapper;
import com.zucc.entity.base.MyMapper;
import com.zucc.exception.SyzxException;
import com.zucc.service.AttachmentService;
import com.zucc.service.base.MyServiceImpl;
import com.zucc.service.base.PageData;
import com.zucc.util.MyPageUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @author : charspan
 * @Description :
 * @create : 2021-12-05 3:29 下午
 */
@Service
public class AttachmentServiceImpl extends MyServiceImpl<Attachment> implements AttachmentService {

    @Value("${file.domain}")
    private String domain;

    @Value("${file.root}")
    private String fileRoot;

    @Resource
    private AttachmentMapper attachmentMapper;

    @Override
    public MyMapper<Attachment> mapper() {
        return attachmentMapper;
    }

    @Override
    public PageData<AttachmentResp> page(AttachmentSearchReq req) {
        Example example = new Example(Attachment.class);
        example.setOrderByClause("modify_time DESC");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);
        if (Objects.nonNull(req.getTypeDictItemId())) {
            criteria.andEqualTo("typeDictItemId", req.getTypeDictItemId());
        }
        if (Objects.nonNull(req.getBuzId())) {
            criteria.andEqualTo("buzId", req.getBuzId());
        }
        if (StrUtil.isNotBlank(req.getOldName())) {
            criteria.andLike("oldName", "%" + req.getOldName() + "%");
        }
        PageData<Attachment> pageData = super.findByPage(req, example);
        PageData<AttachmentResp> convert = MyPageUtil.convert(pageData, AttachmentResp.class);
        return convert;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AttachmentResp upload(Long id, Long buzId, MultipartFile file) {
        // 判断文件是否为空
        if (file.isEmpty()) {
            throw new SyzxException("上传附件失败");
        }
        try {
            String filesRoot = fileRoot + "/" + DateUtil.today() + "/";
            String fileName = file.getOriginalFilename();
            String prefix = "." + fileName.substring(fileName.lastIndexOf(".") + 1);
            String newFileName = RandomUtil.randomNumbers(15) + prefix;
            // 文件保存路径
            String filePath = filesRoot + newFileName;
            File fileDir = new File(filesRoot);
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            File newFile = new File(filePath);
            if (!newFile.exists()) {
                newFile.createNewFile();
            }
            file.transferTo(new File(filePath));
            Attachment attachment = new Attachment();
            attachment.setDelFlag(0);
            attachment.setCreateTime(DateUtil.date());
            attachment.setModifyTime(DateUtil.date());
            attachment.setBuzId(buzId);
            attachment.setSize(Integer.parseInt(String.valueOf(file.getSize())));
            attachment.setOldName(fileName);
            attachment.setTypeDictItemId(id);
            attachment.setName(newFileName);
            attachment.setUri(filePath);
            super.saveKey(attachment);
            AttachmentResp resp = new AttachmentResp();
            BeanUtil.copyProperties(attachment, resp);
            return resp;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SyzxException("上传附件失败");
        }
    }

    @Resource
    private ResourceMapper resourceMapper;

    @Override
    public void download(Long id, HttpServletResponse resp) {
        // 更新下载次数
        Example exp = new Example(com.zucc.entity.Resource.class);
        exp.createCriteria().andEqualTo("delFlag", 0)
                .andEqualTo("attachmentId", id);
        com.zucc.entity.Resource resource = resourceMapper.selectOneByExample(exp);
        if (Objects.nonNull(resource)) {
            resource.setDownloadTimes(resource.getDownloadTimes() + 1);
            resource.setModifyTime(DateUtil.date());
            resourceMapper.updateByPrimaryKeySelective(resource);
        }
        Attachment attachment = super.findById(id);
        if (Objects.isNull(attachment) || attachment.getDelFlag() == 1) {
            throw new SyzxException("附件不存在");
        }

        try {
            // path是指欲下载的文件的路径。
            String path = attachment.getUri();
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            resp.reset();
            // 设置response的Header
            resp.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            resp.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(resp.getOutputStream());
            resp.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 下载模板文件
     *
     * @param response
     * @param inFileName
     * @param outFileNam
     */
    @Override
    public void downloadFile(HttpServletResponse response, String inFileName, String outFileNam) {
        InputStream inputStream = null;
        try {
            response.reset();
            //设置输出文件格式
            response.setContentType("application/vnd.ms-excel");
            outFileNam = URLEncoder.encode(outFileNam, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + outFileNam);
//            response.setHeader("Content-Disposition", "attachment;filename=" + new String(outFileNam.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            ServletOutputStream outputStream = response.getOutputStream();
            inputStream = this.getClass().getResourceAsStream("/templates/" + inFileName);
            byte[] buff = new byte[1024];
            int length;
            while ((length = inputStream.read(buff)) != -1) {
                outputStream.write(buff, 0, length);
            }
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
